package com.ruoyi.bizsys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.bizsys.domain.AwardActConfigRelation;
import com.ruoyi.bizsys.query.AwardConfigQuery;
import com.ruoyi.bizsys.service.IAwardActConfigRelationService;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.RspEnmu;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.bizsys.domain.AwardConfig;
import com.ruoyi.bizsys.mapper.AwardConfigMapper;
import com.ruoyi.bizsys.service.IAwardConfigService;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 奖励配置Service业务层处理
 *
 * @author african-loan
 * @date 2022-06-22
 */
@Service
public class AwardConfigServiceImpl extends ServiceImpl<AwardConfigMapper, AwardConfig> implements IAwardConfigService {

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private IAwardActConfigRelationService awardActConfigRelationService;

    private static final String AWARD_CONFIG_INSERT_LOCK = "AWARD_CONFIG_INSERT_LOCK:%s";

    /**
     * 查询奖励配置
     *
     * @param id 奖励配置ID
     * @return 奖励配置
     */
    @Override
    public AwardConfig selectAwardConfigById(Long id) {
        return this.getById(id);
    }

    /**
     * 查询奖励配置列表
     *
     * @param awardConfigQuery 奖励配置
     * @return 奖励配置
     */
    @Override
    public List<AwardConfig> selectAwardConfigList(AwardConfigQuery awardConfigQuery) {
        LambdaQueryWrapper<AwardConfig> lambdaQueryWrapper = new QueryWrapper<AwardConfig>().last("order by id desc").lambda();
        if(StringUtils.isNotEmpty(awardConfigQuery.getIds())){
            lambdaQueryWrapper.in(AwardConfig::getId,awardConfigQuery.getIds().split(","));
        }
        if(StringUtils.isNotEmpty(awardConfigQuery.getCode())){
            lambdaQueryWrapper.like(AwardConfig::getCode,awardConfigQuery.getCode());
        }
        if(StringUtils.isNotEmpty(awardConfigQuery.getAwardEventType())){
            lambdaQueryWrapper.eq(AwardConfig::getAwardEventType,awardConfigQuery.getAwardEventType());
        }
        if(StringUtils.isNotEmpty(awardConfigQuery.getAwardContent())){
            lambdaQueryWrapper.eq(AwardConfig::getAwardContent,awardConfigQuery.getAwardContent());
        }
        if(StringUtils.isNotEmpty(awardConfigQuery.getAwardMethod())){
            lambdaQueryWrapper.eq(AwardConfig::getAwardMethod,awardConfigQuery.getAwardMethod());
        }
        if(StringUtils.isNotEmpty(awardConfigQuery.getState())){
            lambdaQueryWrapper.eq(AwardConfig::getState,awardConfigQuery.getState());
        }
        return this.list(lambdaQueryWrapper);
    }

    /**
     * 新增奖励配置
     *
     * @param awardConfig 奖励配置
     * @return 结果
     */
    @Override
    public int insertAwardConfig(AwardConfig awardConfig) {
        awardConfig.setCreateTime(DateUtils.getNowDate());
        int resultCode = 0;
        assert StringUtils.isNotEmpty(awardConfig.getAwardEventType());
        String lockKey = String.format(AWARD_CONFIG_INSERT_LOCK, awardConfig.getAwardEventType());
        try{
            boolean isLock = redisCache.tryLock(lockKey); //默认尝试加锁10s，60s释放
            if(!isLock){
                throw new BusinessException(RspEnmu.REQUEST_ERR);
            }
            this.checkAwardEventType(awardConfig.getAwardEventType(),null);
            resultCode = baseMapper.insert(awardConfig);
        }finally {
            redisCache.unlock(lockKey);
        }
        return resultCode;
    }

    /**
     * 修改奖励配置
     *
     * @param awardConfig 奖励配置
     * @return 结果
     */
    @Override
    public int updateAwardConfig(AwardConfig awardConfig) {
        int resultCode = 0;
        awardConfig.setUpdateTime(DateUtils.getNowDate());
        assert StringUtils.isNotEmpty(awardConfig.getAwardEventType());
        String lockKey = String.format(AWARD_CONFIG_INSERT_LOCK, awardConfig.getAwardEventType());
        try {
            boolean isLock = redisCache.tryLock(lockKey); //默认尝试加锁10s，60s释放
            if(!isLock){
                throw new BusinessException(RspEnmu.REQUEST_ERR);
            }
            this.checkAwardEventType(awardConfig.getAwardEventType(),awardConfig.getId());
            resultCode = baseMapper.updateById(awardConfig);
        }finally {
            redisCache.unlock(lockKey);
        }
        return resultCode;
    }

    /**
     * 批量删除奖励配置
     *
     * @param ids 需要删除的奖励配置ID
     * @return 结果
     */
    @Override
    public int deleteAwardConfigByIds(Long[] ids) {
        this.checkAwardConfigRelAct(ids);
        return baseMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除奖励配置信息
     *
     * @param id 奖励配置ID
     * @return 结果
     */
    @Override
    public int deleteAwardConfigById(Long id) {
        return baseMapper.deleteById(id);
    }

    //检查奖励配置是否被活动关联
    private void checkAwardConfigRelAct(Long[] ids){
        List<AwardActConfigRelation> awardActConfigRelations = awardActConfigRelationService.list(new LambdaQueryWrapper<AwardActConfigRelation>().in(AwardActConfigRelation::getConfigId,ids));
        if(!CollectionUtils.isEmpty(awardActConfigRelations)){
            String configIds = awardActConfigRelations.stream().map(obj->String.valueOf(obj.getConfigId())).distinct().collect(Collectors.joining(","));
            Map msgParams = new HashMap();
            msgParams.put("ids",configIds);
            throw new BusinessException(RspEnmu.AWARD_CONFIG_USING,msgParams);
        }
    }

    //检查awardEventType是否存在
    private void checkAwardEventType(String awardEventType,Long id){
        AwardConfig awardConfig = baseMapper.selectOne(new LambdaQueryWrapper<AwardConfig>().eq(AwardConfig::getAwardEventType,awardEventType));
        if(awardConfig==null){
            return;
        }
        if(awardConfig.getId().equals(id)){
            return;
        }
        throw new BusinessException(RspEnmu.AWARD_CONFIG_IS_EXIST);
    }

}
